package com.haoze.nurseapp.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.haoze.common.enumeration.ConstantEnum;
import com.haoze.common.enumeration.StateEnum;
import com.haoze.common.exception.ServiceException;
import com.haoze.common.model.OrdersFileIndexDataEntity;
import com.haoze.common.model.OrdersFileIndexEntity;
import com.haoze.common.model.TaskExecuteBatchEntity;
import com.haoze.common.response.Result;
import com.haoze.common.response.ResultGenerator;
import com.haoze.common.utils.DateUtil;
import com.haoze.common.utils.ListUtils;
import com.haoze.common.utils.UUIDUtil;
import com.haoze.nurseapp.dao.*;
import com.haoze.nurseapp.dto.ConditionDetailsDTO;
import com.haoze.nurseapp.dto.ConvertDataDTO;
import com.haoze.nurseapp.dto.FileIndexDataDTO;
import com.haoze.nurseapp.enumeration.BatchFlagEnum;
import com.haoze.nurseapp.enumeration.TaskEnum;
import com.haoze.nurseapp.model.*;
import com.haoze.nurseapp.service.TaskService;
import com.haoze.nurseapp.service.UserService;
import com.haoze.nurseapp.service.feign.DataSetValueCommonService;
import com.haoze.nurseapp.vo.Element;
import com.haoze.nurseapp.vo.EmrFileData;
import oracle.sql.TIMESTAMP;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;
import tk.mybatis.mapper.entity.Condition;

import javax.annotation.Resource;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.BufferedReader;
import java.io.IOException;
import java.sql.Clob;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @author zh
 */
@Service
public class TaskServiceImpl implements TaskService {

    private static final Logger logger = LoggerFactory.getLogger(TaskServiceImpl.class);
    @Resource
    UserMapper userMapper;
    @Resource
    TaskExecuteDetailMapper taskExecuteDetailMapper;
    @Resource
    TaskExecuteMapper taskExecuteMapper;
    @Resource
    TaskExecuteBatchMapper taskExecuteBatchMapper;
    @Resource
    TaskNodeMapper taskNodeMapper;
    @Resource
    TaskNodeConditionMapper taskNodeConditionMapper;
    @Resource
    TaskNodeConditionDetailMapper taskNodeConditionDetailMapper;
    @Resource
    DataSetValueCommonService dataSetValueCommonService;
    @Resource
    OrdersFileIndexDataMapper ordersFileIndexDataMapper;
    @Resource
    EmrFileMapper emrFileMapper;
    @Resource
    SqlSessionFactory sqlSessionFactory;
    @Resource
    EmrTemplateMapper emrTemplateMapper;
    @Resource
    NodeMapper nodeMapper;
    @Resource
    PatientMapper patientMapper;
    @Resource
    EmrFileIndexEntityMapper emrFileIndexEntityMapper;
    @Resource
    TaskExecutorMapper taskExecutorMapper;

    /**
     * //日期类型
     */
    private static final String ELEMENT_TYPE_THREE="3";
    /**
     * 单选类型
     */
    private static final String TYPE_SIGNLE_SELECTION = "6";
    /**
     * 多选类型
     */
    private static final String TYPE_MULTIPLE_SELECTION = "7";
    /**
     *
     */
    private static final String SPECIAL_SPLITER = "\\$€\\$€\\$";
    /**
     *
     */
    public static final String SWITCH_ON = "1";
    ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript");

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result createNextTaskNode(String userId,String inpatNum,String qrCode,String currentDetailId,String inpatorderdataId,Long batchNo,String groupId,String executeBeginTime,String orderQrCode){
        LocalDateTime now = LocalDateTime.now();

        TaskExecuteDetailEntity currentDetailEntity = taskExecuteDetailMapper.selectByPrimaryKey(currentDetailId);
        TaskExecuteEntity taskExecuteEntity = taskExecuteMapper.selectByPrimaryKey(currentDetailEntity.getTaskExecuteId());
        logger.info("{} 触发任务下一个节点 用户ID：{} 当前任务执行明细ID：{}", inpatorderdataId, userId, currentDetailId);
        currentDetailEntity.setEndDatetime(DateUtil.localDateTime2Date(now));
        currentDetailEntity.setModifyTime(DateUtil.localDateTime2Date(now));
        currentDetailEntity.setStatus(TaskEnum.EXECUTED.getValue());
        taskExecuteDetailMapper.updateByPrimaryKeySelective(currentDetailEntity);

        TaskExecuteBatchEntity currentBatchEntity = taskExecuteBatchMapper.getLastBatchEntity(inpatorderdataId, ""+batchNo);
        currentBatchEntity.initUpdate();
        currentBatchEntity.setStopDatetime(new Timestamp(DateUtil.localDateTime2Date(now).getTime()));
        currentBatchEntity.setExecutePersonId(userId);
        currentBatchEntity.setStatus(TaskEnum.EXECUTED.getValue());
        taskExecuteBatchMapper.updateByPrimaryKeySelective(currentBatchEntity);
        currentBatchEntity.initUpdate();
        currentBatchEntity.setStopDatetime(new Timestamp(DateUtil.localDateTime2Date(now).getTime()));
        currentBatchEntity.setExecutePersonId(userId);
        currentBatchEntity.setStatus(TaskEnum.EXECUTED.getValue());
        taskExecuteBatchMapper.updateByPrimaryKeySelective(currentBatchEntity);

        TaskNodeEntity taskNodeEntity = taskNodeMapper.selectByPrimaryKey(currentDetailEntity.getTaskNodeId());
        //节点已出结果发送通知
//        if (!StateEnum.LEVEL_NO_NOTIFY.getValue().equals(taskNodeEntity.getNotifyLevel())) {
//            sendNotice(taskNodeEntity, taskExecuteEntity, msgContent);
//        }
        //判断下个节点触发条件
        boolean triggerNextNode = false;
        List<FileIndexDataDTO> dataEntityList = ordersFileIndexDataMapper.getAllFileIndexDataByTask(taskExecuteEntity.getTaskExecuteId(), currentDetailId);
        Condition condition = new Condition(TaskNodeConditionEntity.class);
        condition.createCriteria().andEqualTo("preTaskNodeId", taskNodeEntity.getTaskNodeId());
        condition.orderBy("priority");
        List<TaskNodeConditionEntity> taskConditions = taskNodeConditionMapper.selectByCondition(condition);
        List<ConditionDetailsDTO> taskConditionElements = taskNodeConditionDetailMapper.getConditionElements(taskNodeEntity.getTaskNodeId());
        Map<String, Map<String, Object>> datasetMap = getDatasetMap(taskConditionElements, taskExecuteEntity.getInpatNum());

        //判断医嘱开立者
        Boolean isCreator = false;
        TaskNodeConditionEntity selectedTaskCondition = null;

        for (TaskNodeConditionEntity taskCondition : taskConditions) {
            selectedTaskCondition = taskCondition;
            String formula = taskCondition.getFormula();
            //查询节点对应的节点明细的数据元
            if (StringUtils.isBlank(formula)) {
                logger.info("{} 找到无条件执行的路径，结束循环。", inpatorderdataId);
                //公式为空直接执行下个节点
                triggerNextNode = true;
                break;
            }
            List<ConditionDetailsDTO> conditionElements = taskConditionElements.stream().filter(conditionDetailsDTO ->
                    conditionDetailsDTO.getConditionId().equals(taskCondition.getConditionId())).collect(Collectors.toList());
            //匹配引用数据集
            formula = matchQuoteDataSetValue(formula, conditionElements, datasetMap);
            //匹配引用模板明细
            formula = matchQuoteTplDetail(formula, conditionElements, taskExecuteEntity.getInpatorderdataId(), taskExecuteEntity.getInpatNum(), taskExecuteEntity, currentDetailId);
            //匹配医嘱文书数据元值
            formula = matchDataValue(formula, conditionElements, dataEntityList);
            try {
                triggerNextNode = (Boolean) jse.eval(formula);
            } catch (ScriptException e) {
                logger.info("医嘱：{} 条件JS（{}）执行出错。", inpatorderdataId, formula);
                logger.error("条件JS执行出错", e);
                return ResultGenerator.genFailedResult("任务流执行出错，无法继续。");
            }
            if (triggerNextNode == true) {
                logger.info("医嘱：{} 找到符合条件的路径，结束循环。", inpatorderdataId);
                break;
            }
        }
        if (triggerNextNode) {
            //生成下一个任务节点执行明细以及执行对象
            TaskNodeEntity nextTaskNodeEntity = taskNodeMapper.selectByPrimaryKey(selectedTaskCondition.getTaskNodeId());
            //医嘱开立者
            if (TaskEnum.CREATER.getValue().equals(nextTaskNodeEntity.getExecuteType())) {
                isCreator = true;
            }
            TaskExecuteDetailEntity nextDetailEntityParam = new TaskExecuteDetailEntity();
            nextDetailEntityParam.setTaskExecuteId(taskExecuteEntity.getTaskExecuteId());
            nextDetailEntityParam.setTaskNodeId(selectedTaskCondition.getTaskNodeId());
            List<TaskExecuteDetailEntity> taskExecuteDetailEntities = taskExecuteDetailMapper.queryByEntity(nextDetailEntityParam);
            TaskExecuteDetailEntity nextDetailEntity = new TaskExecuteDetailEntity();
            nextDetailEntity.initAdd();
            nextDetailEntity.setTaskExecuteDetailId(UUIDUtil.randomString());
            nextDetailEntity.setTaskExecuteId(taskExecuteEntity.getTaskExecuteId());
            nextDetailEntity.setTaskNodeId(selectedTaskCondition.getTaskNodeId());
            nextDetailEntity.setSerialNo(currentDetailEntity.getSerialNo() + 1);
            nextDetailEntity.setStatus(TaskEnum.UNEXECUTED.getValue());
            nextDetailEntity.setBeginDatetime(StringUtils.isBlank(executeBeginTime) ? DateUtil.localDateTime2Date(now) : DateUtil.stringToDate(executeBeginTime));
            nextDetailEntity.setGroupId(groupId);
            nextDetailEntity.setQrCode(currentDetailEntity.getQrCode());
            nextDetailEntity.setBarCode(currentDetailEntity.getBarCode());
            nextDetailEntity.setParentDetailId(currentDetailId);

            TaskExecuteBatchEntity nextExecuteBatchEntity = new TaskExecuteBatchEntity();
            nextExecuteBatchEntity.setBatchNo(batchNo);
            nextExecuteBatchEntity.setTaskExecuteDetailId(nextDetailEntity.getTaskExecuteDetailId());
            nextExecuteBatchEntity.setTaskNodeId(selectedTaskCondition.getTaskNodeId());
            nextExecuteBatchEntity.setBatchFlag(BatchFlagEnum.BATCH_FLAG_0.getKey());
            List<TaskExecuteBatchEntity> taskExecuteBatchEntities = taskExecuteBatchMapper.select(nextExecuteBatchEntity);
            if (!TaskEnum.TASK.getValue().equals(nextTaskNodeEntity.getType()) && ListUtils.isBlack(taskConditionElements)) {
                OrdersFileIndexEntity emrFileIndexEntity = createTaskNodeOrderFileIndex(userId, taskExecuteEntity, selectedTaskCondition.getTaskNodeId(), currentDetailId, "",inpatNum);
                nextDetailEntity.setEmrFileId(emrFileIndexEntity.getEmrFileId());

                TaskExecuteBatchEntity nextBatchEntity = new TaskExecuteBatchEntity();
                nextBatchEntity.initAdd();
                nextBatchEntity.setTaskBatchId(UUIDUtil.randomString());
                nextBatchEntity.setEmrFileId(emrFileIndexEntity.getEmrFileId());
                nextBatchEntity.setStatus(TaskEnum.UNEXECUTED.getValue());
                nextBatchEntity.setInpatorderdataId(inpatorderdataId);
                nextBatchEntity.setSerialNo(currentBatchEntity.getSerialNo() + 1);
                nextBatchEntity.setBatchNo(batchNo);
                nextBatchEntity.setTaskExecuteId(nextDetailEntity.getTaskExecuteId());
                nextBatchEntity.setTaskNodeId(nextDetailEntity.getTaskNodeId());
                nextBatchEntity.setBarCode(nextDetailEntity.getBarCode());
                nextBatchEntity.setQrCode(orderQrCode);
                nextBatchEntity.setBatchFlag(BatchFlagEnum.BATCH_FLAG_0.getKey());
                nextBatchEntity.setTaskExecuteDetailId(nextDetailEntity.getTaskExecuteDetailId());
                nextBatchEntity.setStartDatetime(StringUtils.isBlank(executeBeginTime) ? new Timestamp(DateUtil.localDateTime2Date(now).getTime()) : DateUtil.stringToTimestamp(executeBeginTime));
                taskExecuteBatchMapper.insertSelective(nextBatchEntity);

                TaskExecutorEntity taskExecutorEntity = new TaskExecutorEntity();
                taskExecutorEntity.initAdd();
                taskExecutorEntity.setExecutorId(UUIDUtil.randomString());
                taskExecutorEntity.setTaskExecuteDetailId(nextDetailEntity.getTaskExecuteDetailId());
                if (TaskEnum.DEPT.getValue().equals(nextTaskNodeEntity.getExecuteType())) {
                    taskExecutorEntity.setExecutorDeptId(nextTaskNodeEntity.getDeptId());
                }else if (TaskEnum.POSITION.getValue().equals(nextTaskNodeEntity.getExecuteType())) {
                    taskExecutorEntity.setExecutorPositionId(nextTaskNodeEntity.getPositionId());
                }else if (TaskEnum.PERSON.getValue().equals(nextTaskNodeEntity.getExecuteType())) {
                    taskExecutorEntity.setExecutorPersonId(nextTaskNodeEntity.getPersonId());
                }
                taskExecutorMapper.insertSelective(taskExecutorEntity);
            }
            //判断该执行节点是否触发子任务
            if (TaskEnum.TASK.getValue().equals(nextTaskNodeEntity.getType())) {
                logger.info("医嘱：{} 生成子任务执行。", inpatorderdataId);
                Condition subCondition = new Condition(TaskNodeEntity.class);
                subCondition.createCriteria().andEqualTo("taskId", nextTaskNodeEntity.getNodeId())
                        .andEqualTo("headFlag", "1");
                TaskNodeEntity subTaskNodeEntity = taskNodeMapper.selectByCondition(subCondition).get(0);
                //创建任务节点对应文书
                OrdersFileIndexEntity emrFileIndexEntity = createTaskNodeOrderFileIndex(userId, taskExecuteEntity, subTaskNodeEntity.getTaskNodeId(), "", "",inpatNum);
                //创建子任务执行
                TaskExecuteDetailEntity taskExecuteDetailEntity = createTaskExecute(nextDetailEntity.getTaskExecuteDetailId(), batchNo, taskExecuteEntity.getInpatorderdataId(), TaskEnum.UNEXECUTED.getValue(), subTaskNodeEntity, emrFileIndexEntity, now, orderQrCode,null,userId);
//            if (TaskEnum.STRATEGY_ONE.getValue().equals(nextTaskNodeEntity.getStrategy())) {
//                //根据子任务创建人物对应频次
//                Long finalBatchNo = batchNo;
//                TaskExecuteDetailEntity finalTaskExecuteDetailEntity = taskExecuteDetailEntity;
//                String finalOrderQrCode = orderQrCode;
//                String finalUserId = userId;
//                fixedThreadPool.execute(() -> createInjections2(finalTaskExecuteDetailEntity, patientOrders, finalOrderQrCode, subTaskNodeEntity.getTaskId(), finalBatchNo, finalUserId, emrFileIndexEntity));
//            }
            }


        }
        //所有的下个节点条件都不符合，则结束任务执行
        TaskExecuteDetailEntity parentTaskDetail = taskExecuteDetailMapper.selectByPrimaryKey(taskExecuteEntity.getTaskExecuteId());

        //判断是否存在父任务，存在则更新父任务结束时间
        if (parentTaskDetail != null) {
            parentTaskDetail.setStatus(TaskEnum.EXECUTED.getValue());
            parentTaskDetail.setEndDatetime(new Date());
            taskExecuteDetailMapper.updateByPrimaryKey(parentTaskDetail);

            TaskExecuteEntity parentTaskExecute = new TaskExecuteEntity();
            parentTaskExecute.setTaskExecuteId(parentTaskDetail.getTaskExecuteId());
            parentTaskExecute.setEndDatetime(DateUtil.localDateTime2Date(now));
            taskExecuteMapper.updateByPrimaryKeySelective(parentTaskExecute);
        }
        taskExecuteEntity.setEndDatetime(DateUtil.localDateTime2Date(now));
        taskExecuteMapper.updateByPrimaryKeySelective(taskExecuteEntity);

        return ResultGenerator.genOkResult();

    }

    /**
     *
     * @param startNode 起始任务节点的varCode
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public TaskExecuteDetailEntity createTaskExecute(String taskExecuteId, Long batchNo, String inpatorderdataId, String execeted, TaskNodeEntity taskNodeEntity,
                                                     OrdersFileIndexEntity emrFileIndex, LocalDateTime localDateTime, String orderQrCode,String startNode,String userId) {
        Date date = DateUtil.localDateTime2Date(localDateTime);
        if (taskNodeEntity == null) {
            if(StringUtils.isBlank(startNode)){
                logger.info("无法找到任务起始的节点", inpatorderdataId);
                throw new ServiceException("无法找到任务起始的节点。");
            }
            taskNodeEntity = taskNodeMapper.getOrderBeginTaskNode(startNode);
            if (taskNodeEntity == null) {
                logger.info("无法找到任务起始的节点", inpatorderdataId);
                throw new ServiceException("无法找到任务起始的节点。");
            }
        }
        //新增任务执行
        TaskExecuteEntity taskExecuteEntity = new TaskExecuteEntity();
        taskExecuteEntity.initAdd();
        taskExecuteEntity.setTaskExecuteId(taskExecuteId);
        taskExecuteEntity.setOutpatNum(emrFileIndex.getOutpatNum());
        taskExecuteEntity.setInpatNum(emrFileIndex.getInpatNum());
        taskExecuteEntity.setDeptId(emrFileIndex.getDeptId());
        taskExecuteEntity.setInpatorderdataId(inpatorderdataId);
        taskExecuteEntity.setWardDeptId(emrFileIndex.getWardDeptId());
        taskExecuteEntity.setTaskId(taskNodeEntity.getTaskId());
        taskExecuteEntity.setBeginDatetime(date);
        taskExecuteMapper.insertSelective(taskExecuteEntity);
        //新增任务执行起始节点明细
        TaskExecuteDetailEntity startDetailEntity = new TaskExecuteDetailEntity();
        startDetailEntity.initAdd();
        startDetailEntity.setTaskExecuteDetailId(UUIDUtil.randomString());
        startDetailEntity.setTaskExecuteId(taskExecuteEntity.getTaskExecuteId());
        startDetailEntity.setTaskNodeId(taskNodeEntity.getTaskNodeId());
        startDetailEntity.setSerialNo(1);
        startDetailEntity.setBeginDatetime(date);
        startDetailEntity.setEmrFileId(emrFileIndex.getEmrFileId());
        startDetailEntity.setStatus(execeted);
        startDetailEntity.setExecutePersonId(emrFileIndex.getDoctorId());
        taskExecuteDetailMapper.insertSelective(startDetailEntity);
        TaskExecuteBatchEntity batchEntity = new TaskExecuteBatchEntity();
        batchEntity.initAdd();
        batchEntity.setTaskBatchId(UUIDUtil.randomString());
        batchEntity.setEmrFileId(emrFileIndex.getEmrFileId());
        batchEntity.setStatus(execeted);
        batchEntity.setQrCode(StringUtils.isEmpty(orderQrCode)?inpatorderdataId:orderQrCode);
        batchEntity.setInpatorderdataId(inpatorderdataId);
        batchEntity.setBatchFlag(BatchFlagEnum.BATCH_FLAG_0.getKey());
        int serialNo = taskExecuteBatchMapper.getMaxSerialNo(inpatorderdataId, batchNo);
        batchEntity.setSerialNo(serialNo);
        batchEntity.setBatchNo(batchNo);
        batchEntity.setTaskNodeId(taskNodeEntity.getTaskNodeId());
        batchEntity.setTaskExecuteId(taskExecuteEntity.getTaskExecuteId());
        batchEntity.setTaskExecuteDetailId(startDetailEntity.getTaskExecuteDetailId());
        batchEntity.setStartDatetime(new Timestamp(date.getTime()));
        taskExecuteBatchMapper.insertSelective(batchEntity);
//生成任务执行对象
        TaskExecutorEntity taskExecutorEntity = new TaskExecutorEntity();
        taskExecutorEntity.initAdd();
        taskExecutorEntity.setExecutorId(UUIDUtil.randomString());
        taskExecutorEntity.setTaskExecuteDetailId(startDetailEntity.getTaskExecuteDetailId());
        if (TaskEnum.DEPT.getValue().equals(taskNodeEntity.getExecuteType())) {
            taskExecutorEntity.setExecutorDeptId(taskNodeEntity.getDeptId());
        }else if (TaskEnum.POSITION.getValue().equals(taskNodeEntity.getExecuteType())) {
            taskExecutorEntity.setExecutorPositionId(taskNodeEntity.getPositionId());
        }else if (TaskEnum.PERSON.getValue().equals(taskNodeEntity.getExecuteType())) {
            taskExecutorEntity.setExecutorPersonId(taskNodeEntity.getPersonId());
        }
        taskExecutorMapper.insertSelective(taskExecutorEntity);

        if (TaskEnum.AUTO.getValue().equals(taskNodeEntity.getExecuteType())) {
            logger.info("医嘱：{} 自动结束节点，开始创建下一节点。", inpatorderdataId);
            createNextTaskNode( userId, emrFileIndex.getInpatNum(), orderQrCode,startDetailEntity.getTaskExecuteDetailId(),"",batchNo,"","","");
        }

        return startDetailEntity;
    }
    private Map<String, Map<String, Object>> getDatasetMap(List<ConditionDetailsDTO> taskConditionElements, String inpatNum) {
        Map<String, Map<String, Object>> datasetMap = new HashMap<>();
        List<String> dataSetList = taskConditionElements.stream().filter(conditionDetailsDTO -> conditionDetailsDTO.getQuoteDatasetId() != null)
                .map(conditionDetailsDTO -> conditionDetailsDTO.getQuoteDatasetId()).distinct().collect(Collectors.toList());
        for (String datasetId : dataSetList) {
            Map<String, String> params = new HashMap<String, String>();
            params.put("DATASET_ID", datasetId);
            params.put("inpatNum", inpatNum);
            Result result = dataSetValueCommonService.commonDataSetValue(params);
            if (result.getCode() == 200) {
                Map map = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), Map.class);
                datasetMap.put(datasetId, map);
            }
        }
        return datasetMap;
    }
    /**
     * 获取模板中引用的数据集数据
     *
     * @param tplId    模板ID
     * @param inpatNum 住院号
     * @param reqNum   电子申请单编号
     * @param serialNo 序列号
     * @param emrType  病历类型
     * @return
     */
    private List<CompletableFuture<Tuple2<String, JSONObject>>> getDatasetMap(String tplId, String inpatNum, String reqNum, String serialNo, String emrType) {
        List<Map<String, String>> datasetList = emrFileMapper.getDatasetListNew(tplId);
        List<CompletableFuture<Tuple2<String, JSONObject>>> futures = datasetList.stream().map(dataset -> {
            return CompletableFuture.supplyAsync(() -> {
                long t1 = System.currentTimeMillis();
                String datasetId = dataset.get("DATASET_ID");
                String url = dataset.get("READ_SERVICE");
                if (StringUtils.isBlank(url)) {
                    return null;
                }
                Map<String, String> params = new HashMap<String, String>();
                params.put("DATASET_ID", datasetId);
                params.put("inpatNum", inpatNum);
                if (StringUtils.isNotBlank(reqNum)) {
                    params.put("reqNum", reqNum);
                }
                if (StringUtils.isNotBlank(serialNo)) {
                    params.put("serialNo", serialNo);
                }
                params.put("emrType", emrType);
                Result result = dataSetValueCommonService.commonDataSetValue(params);
                long t2 = System.currentTimeMillis();
                logger.info("查询第三方接口 {} 数据耗时：{} ms", url, t2 - t1);
                if (result.getCode() == 200) {
                    JSONObject data = JSONObject.parseObject(JSONObject.toJSONString(result.getData()));
                    return Tuples.of(datasetId, data);
                } else {
                    return null;
                }
            });
        }).collect(Collectors.toList());
        return futures;
    }
    private String matchDataValue(String formula, List<ConditionDetailsDTO> conditionElements, List<FileIndexDataDTO> dataEntityList) {
        List<ConditionDetailsDTO> conditionCommonElements = conditionElements.stream().filter(conditionDetailsDTO ->
                StringUtils.isBlank(conditionDetailsDTO.getQuoteDatasetId()) && StringUtils.isBlank(conditionDetailsDTO.getQuoteElementId()) &&
                        StringUtils.isBlank(conditionDetailsDTO.getQuoteTplDetailId()) && StringUtils.isNotBlank(conditionDetailsDTO.getElementId())).collect(Collectors.toList());
        for (ConditionDetailsDTO conditionElement : conditionCommonElements) {
            //下拉框或勾选匹配dataCode
            if (StateEnum.SIMPLE_SEL.getValue().equals(conditionElement.getElementDataType())
                    || StateEnum.CHECK_BOX.getValue().equals(conditionElement.getElementDataType())) {
                boolean match = dataEntityList.stream().anyMatch(fileData -> fileData.getElementId().equals(conditionElement.getElementId()) &&
                        conditionElement.getDataCode().equals(fileData.getDataCode()));
                formula = formula.replace(conditionElement.getConditionDetailId(), String.valueOf(match));
            }
            //多选
            else if (StateEnum.MULTI_SEL.getValue().equals(conditionElement.getElementDataType())) {
                String dataCode = dataEntityList.stream().filter(fileData -> fileData.getElementId().equals(conditionElement.getElementId()))
                        .map(fileData -> fileData.getDataCode()).collect(Collectors.joining());
                boolean match = Arrays.asList(dataCode.split(",")).containsAll(Arrays.asList(conditionElement.getDataCode().split(",")));
                formula = formula.replace(conditionElement.getConditionDetailId(), String.valueOf(match));
            }
            //数值型直接替换公式
            else {
                String dataValue = dataEntityList.stream().filter(fileData -> fileData.getElementId().equals(conditionElement.getElementId())
                        && StringUtils.isNotBlank(fileData.getDataValue())).map(fileData -> fileData.getDataValue()).collect(Collectors.joining());
                if (StringUtils.isBlank(dataValue)) {
                    String temp = formula.substring(formula.indexOf(conditionElement.getConditionDetailId()));
                    int index = StringUtils.indexOfAny(temp, "&&", "||", ")");
                    if (index > 0) {
                        formula = formula.replace(temp.substring(0, index), "false");
                    } else {
                        formula = formula.replace(temp, "false");
                    }
                } else {
                    formula = formula.replace(conditionElement.getConditionDetailId(), dataValue);
                }
            }
        }


        return formula;
    }

    private String matchQuoteDataSetValue(String formula, List<ConditionDetailsDTO> conditionElements, Map<String, Map<String, Object>> datasetMap) {
        List<ConditionDetailsDTO> conditionQuoteElements = conditionElements.stream().filter(conditionDetailsDTO ->
                StringUtils.isNotBlank(conditionDetailsDTO.getQuoteDatasetId()) && StringUtils.isNotBlank(conditionDetailsDTO.getQuoteElementId())).collect(Collectors.toList());
        for (ConditionDetailsDTO conditionElement : conditionQuoteElements) {
            Map<String, Object> dataSetMap = datasetMap.get(conditionElement.getQuoteDatasetId());
            if (dataSetMap != null) {
                String dataCode = "";
                String dataValue = "";
                Object value = dataSetMap.get(conditionElement.getQuoteElementId());
                if (value != null) {
                    switch (conditionElement.getElementDataType()) {
                        case TYPE_SIGNLE_SELECTION:
                        case TYPE_MULTIPLE_SELECTION:
                            try {
                                String[] dataPair = value.toString().split(SPECIAL_SPLITER);
                                if (dataPair.length == 2) {
                                    dataCode = dataPair[0];
                                    dataValue = dataPair[1];
                                } else {
                                    // 麻醉方法代码只能返回文本
                                    dataValue = value.toString().replaceAll(SPECIAL_SPLITER, "");
                                }
                            } catch (Exception e) {
                                logger.error("赋值出错。", e);
                            }
                            break;
                        default:
                            dataValue = value.toString();
                    }
                }
                //下拉框或勾选匹配dataCode
                if (StateEnum.SIMPLE_SEL.getValue().equals(conditionElement.getElementDataType())
                        || StateEnum.CHECK_BOX.getValue().equals(conditionElement.getElementDataType())) {
                    boolean match = conditionElement.getDataCode().equals(dataCode);
                    formula = formula.replace(conditionElement.getConditionDetailId(), String.valueOf(match));
                }
                //多选
                else if (StateEnum.MULTI_SEL.getValue().equals(conditionElement.getElementDataType())) {
                    boolean match = Arrays.asList(dataCode.split(",")).containsAll(Arrays.asList(conditionElement.getDataCode().split(",")));
                    formula = formula.replace(conditionElement.getConditionDetailId(), String.valueOf(match));
                }
                //数值型直接替换公式
                else {
                    if (StringUtils.isBlank(dataValue)) {
                        String temp = formula.substring(formula.indexOf(conditionElement.getConditionDetailId()));
                        int index = StringUtils.indexOfAny(temp, "&&", "||", ")");
                        if (index > 0) {
                            formula = formula.replace(temp.substring(0, index), "false");
                        } else {
                            formula = formula.replace(temp, "false");
                        }
                    } else {
                        formula = formula.replace(conditionElement.getConditionDetailId(), dataValue);
                    }
                }
            } else {
                formula = formula.replace(conditionElement.getConditionDetailId(), "false");
            }
        }
        return formula;
    }

    private String matchQuoteTplDetail(String formula, List<ConditionDetailsDTO> conditionElements, String inpatorderdataId, String inpatNum,
                                       TaskExecuteEntity taskExecuteEntity, String taskExeDetailId) {
        List<ConditionDetailsDTO> conditionQuoteTplElements = conditionElements.stream().filter(conditionDetailsDTO ->
                StringUtils.isNotBlank(conditionDetailsDTO.getQuoteTplDetailId())).collect(Collectors.toList());
        for (ConditionDetailsDTO conditionElement : conditionQuoteTplElements) {
            //查询应用模板数据元
            String dataCode = "";
            String dataValue = "";
            JSONArray priorityArray = JSONArray.parseArray(conditionElement.getQuoteTplDetailId());
            JSONArray totalArray = (JSONArray) priorityArray.get(0);
            JSONObject quoteRule = (JSONObject) totalArray.get(0);
            String quoteCtlId = quoteRule.getString("quoteCtlId");
            List<OrdersFileIndexDataEntity> refDataList;
            if (StateEnum.CATALOG_ORDERS.getValue().equals(quoteRule.getString("quoteNodeType"))) {
                Map<String, String> fileDataByOrder = emrFileMapper.getFileDataByOrder(inpatorderdataId);
                refDataList = emrFileMapper.queryRefOrderData(quoteRule.getString("quoteId"), inpatorderdataId, inpatNum,
                        quoteRule.getString("quoteAll"), quoteRule.getString("isDesc"), fileDataByOrder.get("emrFileId"), fileDataByOrder.get("elementId"));
            } else if (StateEnum.CATALOG_TASKS.getValue().equals(quoteRule.getString("quoteNodeType"))) {
                refDataList = emrFileMapper.queryRefTaskData(quoteRule.getString("quoteId"), quoteCtlId, quoteRule.getString("quoteAll"), quoteRule.getString("isDesc"), taskExecuteEntity.getTaskExecuteId(), taskExeDetailId);
            } else {
                refDataList = emrFileMapper.queryRefData(quoteRule.getString("quoteId"), quoteCtlId, inpatNum, quoteRule.getString("quoteAll"), quoteRule.getString("isDesc"));
            }
            if (!refDataList.isEmpty()) {
                dataCode = refDataList.get(0).getDataCode();
                dataValue = refDataList.get(0).getDataValue();
            }
            //匹配医嘱文书数据元值
            if (StateEnum.SIMPLE_SEL.getValue().equals(conditionElement.getElementDataType())
                    || StateEnum.CHECK_BOX.getValue().equals(conditionElement.getElementDataType())) {   //下拉框或勾选项匹配dataCode
                boolean match = conditionElement.getDataCode().equals(dataCode);
                formula = formula.replace(conditionElement.getConditionDetailId(), String.valueOf(match));
            } else if (StateEnum.MULTI_SEL.getValue().equals(conditionElement.getElementDataType())) {//多选
                boolean match = Arrays.asList(dataCode.split(",")).containsAll(Arrays.asList(conditionElement.getDataCode().split(",")));
                formula = formula.replace(conditionElement.getConditionDetailId(), String.valueOf(match));
            } else {    //数值型直接替换公式
                if (StringUtils.isBlank(dataValue)) {
                    String temp = formula.substring(formula.indexOf(conditionElement.getConditionDetailId()));
                    int index = StringUtils.indexOfAny(temp, "&&", "||", ")");
                    if (index > 0) {
                        formula = formula.replace(temp.substring(0, index), "false");
                    } else {
                        formula = formula.replace(temp, "false");
                    }
                } else {
                    formula = formula.replace(conditionElement.getConditionDetailId(), dataValue);
                }
            }
        }
        return formula;
    }
    private UserEntity getCurrentUser() {
        String userId = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader("zuul_id");
        UserEntity currentUser = userMapper.selectByPrimaryKey(userId);
        return currentUser;
    }
    public OrdersFileIndexEntity createTaskNodeOrderFileIndex(String userId, TaskExecuteEntity taskExecuteEntity, String taskNodeId, String taskExeDetailId, String tplId,String inpatNum) {

        logger.info("创建任务节点对应文书,用户id{},任务执行id{},任务节点id{}", userId, taskExecuteEntity.getTaskExecuteId(), taskNodeId);
        Map<String, String> template;
        if (StringUtils.isNotEmpty(tplId)) {
            template = JSONObject.parseObject(JSONObject.toJSONString(emrTemplateMapper.selectByPrimaryKey(tplId)), Map.class);
        } else {
            template = nodeMapper.getTplByTaskNode(taskNodeId);
        }
        OrdersFileIndexEntity emrFileIndex = new OrdersFileIndexEntity();
        Timestamp currentTime = new Timestamp(System.currentTimeMillis());
        UserEntity currentUser = userMapper.selectByPrimaryKey(userId);
        Map<String, String> patientInfo = patientMapper.getPatientInfo(inpatNum);
        String userName = currentUser.getUserName();
        if (StringUtils.isBlank(userName)) {
            userName = "无名";
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHH");
        String emrFileName = userName + "—" + sdf.format(new Date(currentTime.getTime()));
        emrFileIndex.setEmrFileName(emrFileName);
        emrFileIndex.setHospitalId(taskExecuteEntity.getHospitalId());
        emrFileIndex.setDataVersion(1);
        emrFileIndex.setOutpatNum("0");
        emrFileIndex.setDelFlag(StateEnum.EMR_UNDEL.getValue());
        emrFileIndex.setInpatNum(inpatNum);
        emrFileIndex.setDoctorId(currentUser.getUserId());
        emrFileIndex.setDeptId(patientInfo.get("deptId"));
        emrFileIndex.setWardDeptId(patientInfo.get("wardDeptId"));
        emrFileIndex.setGmtCreate(currentTime);
        emrFileIndex.setGmtModify(currentTime);
        if (template != null) {
            emrFileIndex.setEmrFileId(UUIDUtil.randomString());
            emrFileIndex.setTplId(template.get("tplId"));
        } else {
            return emrFileIndex;
        }
        emrFileIndexEntityMapper.insertSelective(emrFileIndex);
        List<CompletableFuture<Tuple2<String, JSONObject>>> datasetFutures = getDatasetMap(emrFileIndex.getTplId(), emrFileIndex.getInpatNum(), "", "", template.get("emrType"));
        ConvertDataDTO convertDataDTO = new ConvertDataDTO();
        convertDataDTO.setPatientDeptId(patientInfo.get("deptId"));
        convertDataDTO.setPatientDeptName(patientInfo.get("deptName"));
        List<EmrFileData> dataList = createEmrFileData(emrFileIndex, datasetFutures, currentUser, taskExecuteEntity, taskExeDetailId, null, null , convertDataDTO);


        SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
        Map<String, Object> params = new HashMap<>();
        params.put("fileIndex", emrFileIndex);
        dataList.stream().map(data -> data.getFileIndexDataEntity()).forEach(dataEntity -> {
            params.put("dataEntity", dataEntity);
            session.insert("com.haoze.doctor.dao.EmrFileMapper.insertDataList", params);
        });
        session.flushStatements();
        return emrFileIndex;
    }

    private List<EmrFileData> createEmrFileData(OrdersFileIndexEntity emrFileIndex, List<CompletableFuture<Tuple2<String, JSONObject>>> datasetFeatures,
                                                UserEntity currentUser, TaskExecuteEntity taskExecuteEntity, String taskExeDetailId, String preDataCode, String preDataValue, ConvertDataDTO convertDataDTO) {
        long t1 = System.currentTimeMillis();
        List<Map<String, Object>> list = emrTemplateMapper.getEmrFileData(emrFileIndex.getTplId());
        long t2 = System.currentTimeMillis();
        logger.info("{} 模板{}条查询时间：{} ms", emrFileIndex.getTplId(), list.size(), t2 - t1);
        List<EmrFileData> emrFileDataList = convertData(list, currentUser, preDataCode, preDataValue,convertDataDTO);
        Map<String, Map<String, Object>> datasetMap = new HashMap<>(5);
        try {
            CompletableFuture.allOf(datasetFeatures.toArray(new CompletableFuture[datasetFeatures.size()])).thenApply(v -> {
                return datasetFeatures.stream().map(datasetFeature -> datasetFeature.join())
                        .collect(Collectors.toList());
            }).get().stream().filter(tuple2 -> tuple2 != null).forEach(tuple2 -> {
                datasetMap.put(tuple2.getT1(), tuple2.getT2());
            });
        } catch (Exception e) {
            logger.error("查询第三方接口出现错误。", e);
        }
        int orignialSize = emrFileDataList.size();
        for (int i = 0; i < orignialSize; i++) {
            EmrFileData emrFileData = emrFileDataList.get(i);
            OrdersFileIndexDataEntity dataEntity = emrFileData.getFileIndexDataEntity();
            String oldId = dataEntity.getFileIndexDataId();
            String newId = UUIDUtil.randomString();
            dataEntity.setFileIndexDataId(newId);
            Element element = emrFileData.getElement();

            // 引用数据集
            if (StringUtils.isNotBlank(dataEntity.getQuoteDatasetId()) && StringUtils.isNotBlank(dataEntity.getQuoteElementId())) {
                updateQuoteDatasetValue(datasetMap, emrFileData, true);
            }
            // 补充全部勾选项
            if (element.getElementPropertyFormat() != null && element.getElementPropertyFormat().indexOf("\"formatValue\":\"2\"") > -1) {
                element.setSelections(emrFileMapper.getAllSelections(element.getId()));
            }

            // 引用其他病历 新版本
            if (StringUtils.isNotBlank(dataEntity.getQuoteTplDetailId()) && dataEntity.getQuoteTplDetailId().startsWith("[[")) {
                JSONArray priorityArray = JSONArray.parseArray(dataEntity.getQuoteTplDetailId());
                for (Object priorityObj : priorityArray) {
                    JSONArray totalArray = (JSONArray) priorityObj;
                    boolean isFound = totalArray.stream().map(parallelingObj -> {
                        JSONObject quoteRule = (JSONObject) parallelingObj;

                        String quoteCtlId = quoteRule.getString("quoteCtlId");
                        if (StringUtils.isEmpty(quoteCtlId) && taskExecuteEntity == null) {
                            logger.info("缺少目录和医嘱，无法引用。");
                            return false;
                        }
                        List<OrdersFileIndexDataEntity> refDataList;
                        if (StateEnum.CATALOG_ORDERS.getValue().equals(quoteRule.getString("quoteNodeType"))) {
                            if (taskExecuteEntity != null) { // 引用本次医嘱
                                Map<String, String> fileDataByOrder = emrFileMapper.getFileDataByOrder(taskExecuteEntity.getInpatorderdataId());
                                String inpatorderdataId = taskExecuteEntity.getInpatorderdataId();
                                if(StringUtils.isNotBlank(fileDataByOrder.get("fileIndexDataId"))){
                                    inpatorderdataId =fileDataByOrder.get("fileIndexDataId");
                                }
                                refDataList = emrFileMapper.queryRefOrderData(quoteRule.getString("quoteId"), inpatorderdataId, emrFileIndex.getInpatNum(),
                                        quoteRule.getString("quoteAll"), quoteRule.getString("isDesc"), fileDataByOrder.get("emrFileId"), fileDataByOrder.get("elementId"));
                            } else { // 开医嘱时引用上次医嘱
                                refDataList = emrFileMapper.queryRefLastOrderData(quoteRule.getString("quoteId"), quoteCtlId, emrFileIndex.getInpatNum());
                            }
                        } else if (StateEnum.CATALOG_TASKS.getValue().equals(quoteRule.getString("quoteNodeType"))) {
                            refDataList = emrFileMapper.queryRefTaskData(quoteRule.getString("quoteId"), quoteCtlId, quoteRule.getString("quoteAll"), quoteRule.getString("isDesc"), taskExecuteEntity.getTaskExecuteId(), taskExeDetailId);
                        } else {
                            refDataList = emrFileMapper.queryRefData(quoteRule.getString("quoteId"), quoteCtlId, emrFileIndex.getInpatNum(), quoteRule.getString("quoteAll"), quoteRule.getString("isDesc"));
                        }
                        if (refDataList.isEmpty()) { // 引用节点已不存在 忽略
                            return false;
                        }
                        return IntStream.range(0, refDataList.size()).mapToObj(idx -> {
                            OrdersFileIndexDataEntity refData = refDataList.get(idx);
                            if ("Y".equals(quoteRule.getString("oneToOne"))) { // 点对点引用
                                if (StringUtils.isEmpty(refData.getDataValue())) {
                                    return false;
                                }
                                dataEntity.setDataValue(refData.getDataValue());
                                dataEntity.setDataCode(refData.getDataCode());
                                return true; // 有数据 才算找到
                            }
                            // 引用下级节点
                            long t3 = System.currentTimeMillis();
                            // 优先在病历中找
                            List<EmrFileData> refList = getEmrFileData(refData.getEmrFileId(), refData.getFileIndexDataId(), currentUser,convertDataDTO);
                            if (refList.isEmpty()) { // 尝试在医嘱文书中找
                                refList = getOrderFileData(refData.getEmrFileId(), refData.getFileIndexDataId(), currentUser,convertDataDTO);
                            }
                            long t4 = System.currentTimeMillis();
                            logger.info("被引用病历{}条查询时间：{} ms", refList.size(), t4 - t3);
                            if (refList.isEmpty()) { // 无子节点 也算找到了
                                return true;
                            }
                            String type = quoteRule.getString("type");
                            if ("2".equals(type)) { // 医疗术语 引用节点本身也添加进去
                                EmrFileData tempData = new EmrFileData();
                                Element tempElement = new Element();
                                tempElement.setType("20");
                                tempData.setElement(tempElement);
                                tempData.setFileIndexDataEntity(refData);
                                refList.add(0, tempData);
                            }
                            for (int j = 0; j < refList.size(); j++) {
                                EmrFileData subRefData = refList.get(j);
                                subRefData.setFirstQuote(true); // 标记为第一次引用 提示前端不要进行自引用修改
                                OrdersFileIndexDataEntity refDataEntity = subRefData.getFileIndexDataEntity();
                                if ("2".equals(type)) {
                                    if (refDataEntity == refData) { // 医疗术语本身
                                        refDataEntity.setParentFileIndexDataId(newId);
                                    }
                                } else {
                                    if (refDataEntity.getParentFileIndexDataId().equals(refData.getFileIndexDataId())) {
                                        refDataEntity.setParentFileIndexDataId(newId);
                                    }
                                }

                                String subOldId = refDataEntity.getFileIndexDataId();
                                String subNewId = UUIDUtil.randomString();
                                refDataEntity.setFileIndexDataId(subNewId);
                                refDataEntity.setCreateTime(dataEntity.getCreateTime());
                                refDataEntity.setModifyTime(dataEntity.getModifyTime());
                                try {
                                    String elementProperty = refDataEntity.getElementProperty();
                                    JSONObject jsonObject = JSONObject.parseObject(elementProperty);
                                    jsonObject.put("printNewLine", "1");
                                    jsonObject.put("childPrintNewLine", "1");
                                    jsonObject.put("printAlign", "0");
                                    jsonObject.put("printFontBold", "1");
                                    jsonObject.put("printSplitLine", "1");
                                    jsonObject.put("childrenPrintAlign", "0");
                                    jsonObject.put("selfPrintAlign", "0");
                                    if (idx != 0 && j == 0) { // 第一项增加一个换行符号
                                        jsonObject.put("newLine", "0");
                                        jsonObject.put("printNewLine", "0");
                                    }
                                    refDataEntity.setElementProperty(jsonObject.toJSONString());
                                } catch (Exception e) {
                                    logger.error("重置elementProperty出错。", e);
                                }
                                for (int k = j; k < refList.size(); k++) {
                                    EmrFileData subNextData = refList.get(k);
                                    OrdersFileIndexDataEntity subNextDataEntity = subNextData.getFileIndexDataEntity();
                                    if (subOldId.equals(subNextDataEntity.getParentFileIndexDataId())) {
                                        subNextDataEntity.setParentFileIndexDataId(subNewId);
                                    }
                                }
                            }

                            emrFileDataList.addAll(refList);
                            return true;
                        }).reduce(false, (accumulatorBoolean, nextBoolean) -> accumulatorBoolean || nextBoolean);
                    }).reduce(false, (accumulatorBoolean, nextBoolean) -> accumulatorBoolean || nextBoolean);
                    // 如果已经引用到数据 终止循环
                    if (isFound) {
                        break;
                    }
                }
            }
            // 补充父级ID
            for (int j = i + 1; j < orignialSize; j++) {
                EmrFileData nextData = emrFileDataList.get(j);
                if (oldId.equals(nextData.getFileIndexDataEntity().getParentFileIndexDataId())) {
                    nextData.getFileIndexDataEntity().setParentFileIndexDataId(newId);
                }
            }
        }
        return emrFileDataList.parallelStream().filter(emrFileData -> {
            Element element = emrFileData.getElement();
            if ("手术名称".equals(element.getName()) && "手术名称".equals(emrFileData.getFileIndexDataEntity().getDataValue())) {
                emrFileData.getFileIndexDataEntity().setDataValue("-");
            }
            //日期类型
            if (ELEMENT_TYPE_THREE.equals(element.getType())) {
                String time = emrFileData.getFileIndexDataEntity().getDataValue();
                if (StringUtils.isNotBlank(time)) {
                    Date dateStr = null;
                    String dataValue = time;
                    try {
                        if (StringUtils.isNotBlank(element.getFormat())) {//redis中未存elementPropertyFormat 直接取format
                            JSONObject format = JSONObject.parseObject(element.getFormat());
                            String formatValue = format.getString("formatValue");
                            if (StringUtils.isNotBlank(formatValue)) {
                                if ("HH:mm".equals(formatValue)) {
                                    if (time.length() > 11) { //引用其他病历存在 HH:mm 值
                                        dataValue = time.substring(11);
                                    } else {
                                        dataValue = time;
                                    }
                                } else {
                                    SimpleDateFormat sdf = new SimpleDateFormat(formatValue);//格式取数据元定义格式
                                    dateStr = sdf.parse(time);
                                    dataValue = sdf.format(dateStr);
                                }
                            }
                        }
                    } catch (Exception e) {
                        dataValue = time;
                        logger.error("日期数据转换出错。", e);
                    }
                    emrFileData.getFileIndexDataEntity().setDataValue(dataValue);
                }
            }
            return true;
        }).collect(Collectors.toList());
    }
    private List<EmrFileData> convertData(List<Map<String, Object>> list, UserEntity currentUser, String preDataCode, String preDataValue, ConvertDataDTO convertDataDTO) {
        return list.parallelStream().map(map -> {
            // 医嘱类型如果不是不可修改 将和上一个医嘱类型保持一致
            if (StringUtils.isNoneEmpty((String) map.get("VAR_CODE"), preDataCode, preDataValue)
                    && !((String)map.get("ELEMENT_PROPERTY")).contains("\"editIdentification\":\"1\"")
                    && map.get("VAR_CODE").equals("yz_type")) {
                map.put("DATA_CODE", preDataCode);
                map.put("DATA_VALUE", preDataValue);
            }
            EmrFileData data = new EmrFileData();
            OrdersFileIndexDataEntity dataEntity = new OrdersFileIndexDataEntity();
            dataEntity.setFileIndexDataId((String) map.get("FILE_INDEX_DATA_ID"));
            dataEntity.setCreateTime(((Date) map.get("GMT_CREATE")));
            dataEntity.setModifyTime(((Date) map.get("GMT_MODIFY")));
            dataEntity.setSortId((map.get("SORT_ID")) == null ? 0 : ((Number) map.get("SORT_ID")).intValue());
            dataEntity.setElementId((String) map.get("ELEMENT_ID"));
            dataEntity.setParentElementId((String) map.get("PARENT_ELEMENT_ID"));
            dataEntity.setQuoteDatasetId((String) map.get("QUOTE_DATASET_ID"));
            dataEntity.setQuoteElementId((String) map.get("QUOTE_ELEMENT_ID"));
            dataEntity.setDataCode((String) map.get("DATA_CODE"));
            dataEntity.setParentFileIndexDataId((String) map.get("PARENT_FILE_INDEX_DATA_ID"));
            dataEntity.setBaseTplDetailId((String) map.get("BASE_TPL_DETAIL_ID"));
            dataEntity.setQuoteTplDetailId((String) map.get("QUOTE_TPL_DETAIL_ID"));
            String dataValue = "";
            if (map.get("DATA_VALUE_STR") != null) {
                dataValue = (String) map.get("DATA_VALUE_STR");
            } else {
                try {
                    if (map.get("DATA_VALUE") != null) {
                        if (map.get("DATA_VALUE") instanceof Clob) {
                            Clob clob = (Clob) map.get("DATA_VALUE");
                            BufferedReader reader = new BufferedReader(clob.getCharacterStream());
                            dataValue = FileCopyUtils.copyToString(reader);
                        } else {
                            dataValue = (String) map.get("DATA_VALUE");
                        }
                    }
                } catch (SQLException | IOException e) {
                    logger.error("转换对象出错。", e);
                }
            }
            dataEntity.setDataValue(dataValue);
            dataEntity.setFormatDataValue((String) map.get("FORMAT_DATA_VALUE"));
            dataEntity.setPrintIdentification((String) map.get("PRINT_IDENTIFICATION"));
            dataEntity.setShowIdentification((String) map.get("SHOW_IDENTIFICATION"));
            dataEntity.setDeleteIdentification((String) map.get("DELETE_IDENTIFICATION"));
            dataEntity.setElementProperty((String) map.get("ELEMENT_PROPERTY"));
            dataEntity.setMedicalId((String) map.get("MEDICAL_ID"));
            dataEntity.setUnit((String) map.get("UNIT"));
            dataEntity.setExtendedField(map.get("EXTENDED_FIELD") == null ? "" : map.get("EXTENDED_FIELD").toString());
            dataEntity.setFormatDataValue(map.get("FORMAT_DATA_VALUE") == null ? "" : map.get("FORMAT_DATA_VALUE").toString());
            data.setNeedChanged(map.get("NEED_CHANGED") == null ? "1" : map.get("NEED_CHANGED").toString());
            data.setFileIndexDataEntity(dataEntity);
            data.setTplDetailId((String) map.get("TPL_DETAIL_ID"));
            if (currentUser != null && StringUtils.isNotBlank(dataEntity.getElementProperty())) {
                JSONObject property = JSONObject.parseObject(dataEntity.getElementProperty());
                if (SWITCH_ON.equals(property.get("currentUser"))) {
                    dataEntity.setDataCode(currentUser.getPersonId());
                    dataEntity.setDataValue(currentUser.getUserName());
                }
                if (SWITCH_ON.equals(property.get("currentDept"))) {
                    dataEntity.setDataCode(convertDataDTO.getPatientDeptId());
                    dataEntity.setDataValue(convertDataDTO.getPatientDeptName());
                }
                if (SWITCH_ON.equals(property.get("currentTimeStamp"))) {
                    dataEntity.setDataValue(DateUtil.dateToString(new Date(), "yyyy-MM-dd HH:mm"));
                }
            }

            // 补充数据元属性
            Element element = new Element();
            element.setId((String) map.get("ELEMENT_ID"));
            element.setName((String) map.get("ELEMENT_NAME"));
            if (StringUtils.isBlank(element.getName())) {
                element.setDataValue(dataEntity.getDataValue());
            }
            element.setType((String) map.get("ELEMENT_DATA_TYPE_ID"));
            element.setMin(map.get("MIN_VALUE") == null ? null : ((Number) map.get("MIN_VALUE")).doubleValue());
            element.setMax(map.get("MAX_VALUE") == null ? null : ((Number) map.get("MAX_VALUE")).doubleValue());
            element.setUnit(map.get("ELEMENT_UNIT") == null ? null : map.get("ELEMENT_UNIT").toString());
            element.setVarCode((String) map.get("VAR_CODE"));
            element.setMedicalId(dataEntity.getMedicalId());
            element.setFormat((String) map.get("ELEMENT_PROPERTY_FORMAT"));
            element.setElementPropertyFormat((String) map.get("ELEMENT_PROPERTY_FORMAT"));
            element.setIsPreDiag(map.get("IS_PRE_DIAG") == null ? null : map.get("IS_PRE_DIAG").toString());
            data.setElement(element);

            data.setEmrFileDataList(new ArrayList<>());
            return data;
        }).collect(Collectors.toList());
    }

    private void updateQuoteDatasetValue(Map<String, Map<String, Object>> datasetMap, EmrFileData emrFileData, Boolean trigger) {
        OrdersFileIndexDataEntity dataEntity = emrFileData.getFileIndexDataEntity();
        Element element = emrFileData.getElement();
        Map<String, Object> dataset = datasetMap.get(dataEntity.getQuoteDatasetId());
        if (dataset != null) {
            Object value = dataset.get(dataEntity.getQuoteElementId());
            if (value != null) {
                switch (element.getType()) {
                    case TYPE_SIGNLE_SELECTION:
                    case TYPE_MULTIPLE_SELECTION:
                        try {
                            String[] dataPair = value.toString().split(SPECIAL_SPLITER);
                            if (dataPair.length == 2) {
                                dataEntity.setDataCode(dataPair[0]);
                                dataEntity.setDataValue(dataPair[1]);
                                emrFileData.setFirstTrigger(trigger);
                            } else {
                                // 麻醉方法代码只能返回文本
                                dataEntity.setDataValue(value.toString().replaceAll("\\$€\\$€\\$", ""));
                            }
                        } catch (Exception e) {
                            logger.error("赋值出错。", e);
                        }
                        break;
                    default:
                        dataEntity.setDataValue(value.toString());
                }
            }
        }
    }

    /**
     * 查询病历数据列表
     *
     * @param emrFileId             病历ID
     * @param parentFileIndexDataId 父级数据ID 可以为null
     * @return
     */
    public List<EmrFileData> getEmrFileData(String emrFileId, String parentFileIndexDataId, UserEntity currentUser,ConvertDataDTO convertDataDTO) {
        long t1 = System.currentTimeMillis();
        List<Map<String, Object>> list = emrFileMapper.getAllEmrDataEntity(emrFileId, parentFileIndexDataId);

        long t2 = System.currentTimeMillis();
        logger.info("{} 从数据库获取{}条数据时间： {} ms", emrFileId, list.size(), t2 - t1);
        List<EmrFileData> emrFileDataList = convertData(list, currentUser, null, null,convertDataDTO);
        emrFileDataList.stream().forEach(emrFileData -> {
            Element element = emrFileData.getElement();
            // 补充全部勾选项
            if (element.getElementPropertyFormat() != null && element.getElementPropertyFormat().indexOf("\"formatValue\":\"2\"") > -1) {
                element.setSelections(emrFileMapper.getAllSelections(element.getId()));
            }
        });
        return emrFileDataList;
    }
    /**
     * 查询医嘱数据列表
     *
     * @param emrFileId             病历ID
     * @param parentFileIndexDataId 父级数据ID 可以为null
     * @param currentUser
     * @return
     */
    private List<EmrFileData> getOrderFileData(String emrFileId, String parentFileIndexDataId, UserEntity currentUser,ConvertDataDTO convertDataDTO) {
        long t1 = System.currentTimeMillis();
        List<Map<String, Object>> list = emrFileMapper.getAllOrderDataEntity(emrFileId, parentFileIndexDataId);
        long t2 = System.currentTimeMillis();
        logger.info("{} 从数据库获取{}条数据时间： {} ms", emrFileId, list.size(), t2 - t1);
        List<EmrFileData> emrFileDataList = convertData(list, currentUser, null, null,convertDataDTO);
        emrFileDataList.stream().forEach(emrFileData -> {
            Element element = emrFileData.getElement();
            // 补充全部勾选项
            if (element.getElementPropertyFormat() != null && element.getElementPropertyFormat().indexOf("\"formatValue\":\"2\"") > -1) {
                element.setSelections(emrFileMapper.getAllSelections(element.getId()));
            }
        });
        return emrFileDataList;
    }
}
